home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / utils / sound / players / unix / rplay / librplay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-23  |  6.0 KB  |  323 lines

  1. /*
  2.  * librplay.c
  3.  *
  4.  * Copyright (c) 1992 by Mark Boyns
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted, provided
  8.  * that the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation.  This software is provided "as is" without express or
  11.  * implied warranty.
  12.  */
  13.  
  14. #include <sys/types.h>
  15. #include <sys/socket.h>
  16. #include <netinet/in.h>
  17. #include <netdb.h>
  18. #include <varargs.h>
  19. #include <malloc.h>
  20. #include <stdio.h>
  21. #include "version.h"
  22. #include "rplay.h"
  23.  
  24. int     rplay_errno;
  25.  
  26. char    *rplay_errlist[] = {
  27.     "no error",            /* RPLAY_ERROR_NONE */
  28.     "out of memory",        /* RPLAY_ERROR_MEMORY */
  29.     "host not found",        /* RPLAY_ERROR_HOST */
  30.     "rplay service not found",    /* RPLAY_ERROR_SERVICE */
  31.     "cannot connect to socket",    /* RPLAY_ERROR_CONNECT */
  32.     "cannot create socket",        /* RPLAY_ERROR_SOCKET */
  33.     "unknown rplay attribute",    /* RPLAY_ERROR_ATTRIBUTE */
  34.     "error writing to socket",    /* RPLAY_ERROR_WRITE */
  35.     "error closing socket",        /* RPLAY_ERROR_CLOSE */ 
  36.     "append error",            /* RPLAY_ERROR_APPEND */
  37.     "max packet size exceeded",    /* RPLAY_ERROR_PACKET_SIZE */
  38.     "cannot enable broadcast",    /* RPLAY_ERROR_BROADCAST */
  39. };
  40.  
  41. /*
  42.  * macro used to gradually increase an rplay buffer by COPY_SIZE bytes
  43.  */
  44. #define COPY_SIZE    128
  45. #define COPY(rp, ptr, n) \
  46.     rp->grow = 0; \
  47.     while(rp->len + n > rp->size) { \
  48.         rp->grow = 1; \
  49.         rp->size += COPY_SIZE; \
  50.         if (rp->size > MAX_PACKET) { \
  51.             rplay_errno = RPLAY_ERROR_PACKET_SIZE; \
  52.             return -1; \
  53.         } \
  54.     } \
  55.     if (rp->grow) { \
  56.         rp->buf = realloc(rp->buf, rp->size); \
  57.         if (rp->buf == NULL) { \
  58.             rplay_errno =  RPLAY_ERROR_MEMORY; \
  59.             return -1; \
  60.         } \
  61.     } \
  62.     bcopy(ptr, rp->buf+rp->len, n); \
  63.     rp->len += n; \
  64.  
  65. /*
  66.  * create an RPLAY instance
  67.  */
  68. RPLAY    *rplay_create()
  69. {
  70.     RPLAY    *rp;
  71.  
  72.     rplay_errno = RPLAY_ERROR_NONE;
  73.  
  74.     rp = (RPLAY *)malloc(sizeof(RPLAY));
  75.     if (rp == NULL) {
  76.         rplay_errno =  RPLAY_ERROR_MEMORY;
  77.         return NULL;
  78.     }
  79.     else {
  80.         rp->len = 0; 
  81.         rp->buf = (char *)malloc(COPY_SIZE);
  82.         if (rp->buf == NULL) {
  83.             rplay_errno =  RPLAY_ERROR_MEMORY;
  84.             return NULL;
  85.         }
  86.         rp->size = COPY_SIZE;
  87.         return rp;
  88.     }
  89. }
  90.  
  91. /*
  92.  * free up memory used by rp
  93.  */
  94. int    rplay_destroy(rp) 
  95. RPLAY    *rp;
  96.     free(rp->buf);
  97.     free(rp);    
  98.  
  99. /*
  100.  * set rplay attributes
  101.  */
  102. int    rplay_set(va_alist)
  103. va_dcl
  104. {
  105.     va_list        args;
  106.     RPLAY        *rp;
  107.     char        *p;
  108.     unsigned char    val, *valp = &val;
  109.     int        attr, append;
  110.  
  111.     rplay_errno = RPLAY_ERROR_NONE;
  112.  
  113.     va_start(args);
  114.     rp = va_arg(args, RPLAY *);
  115.     attr = va_arg(args, int); 
  116.  
  117.     append = 0;
  118.     switch(attr) {
  119.     case RPLAY_APPEND_PLAY:
  120.         if (rp->len <= 0 || rp->buf[0] != RPLAY_PLAY) {
  121.             rplay_errno = RPLAY_ERROR_APPEND;
  122.             return -1;
  123.         }
  124.         attr = RPLAY_PLAY;
  125.         append = 1;
  126.         break;
  127.  
  128.     case RPLAY_APPEND_PAUSE:
  129.         if (rp->len <= 0 || rp->buf[0] != RPLAY_PAUSE) {
  130.             rplay_errno = RPLAY_ERROR_APPEND;
  131.             return -1;
  132.         }
  133.         attr = RPLAY_PAUSE;
  134.         append = 1;
  135.         break;
  136.  
  137.     case RPLAY_APPEND_STOP: 
  138.         if (rp->len <= 0 || rp->buf[0] != RPLAY_STOP) {
  139.             rplay_errno = RPLAY_ERROR_APPEND;
  140.             return -1;
  141.         }
  142.         attr = RPLAY_STOP;
  143.         append = 1;
  144.         break;
  145.  
  146.     case RPLAY_APPEND_CONTINUE:
  147.         if (rp->len <= 0 || rp->buf[0] != RPLAY_CONTINUE) {
  148.             rplay_errno = RPLAY_ERROR_APPEND;
  149.             return -1;
  150.         }
  151.         attr = RPLAY_CONTINUE;
  152.         append = 1;
  153.         break;
  154.  
  155.     case RPLAY_APPEND_VOLUME_PLAY:
  156.         if (rp->len <= 0 || rp->buf[0] != RPLAY_PLAY) {
  157.             rplay_errno = RPLAY_ERROR_APPEND;
  158.             return -1;
  159.         }
  160.         attr = RPLAY_VOLUME_PLAY;
  161.         append = 1;
  162.         break;
  163.     }
  164.  
  165.     if (append) {
  166.         rp->len--;
  167.     }
  168.     else {
  169.         rp->len = 0;
  170.     }
  171.  
  172.     switch(attr) {  
  173.     case RPLAY_PLAY:
  174.     case RPLAY_PAUSE:
  175.     case RPLAY_STOP: 
  176.     case RPLAY_CONTINUE:
  177.     case RPLAY_VOLUME_PLAY:
  178.         if (!append) {
  179.             *valp = attr == RPLAY_VOLUME_PLAY ? RPLAY_PLAY : attr;
  180.             COPY(rp, valp, 1);
  181.         }
  182.         for(;;) {
  183.             p = va_arg(args, char *);
  184.             if (p == NULL) {
  185.                 *valp = NULL;
  186.                 COPY(rp, valp, 1);
  187.                 break;
  188.             }
  189.             COPY(rp, p, strlen(p)+1);
  190.             if (attr == RPLAY_VOLUME_PLAY) {
  191.                 *valp = (unsigned char)va_arg(args, int);
  192.                 COPY(rp, valp, 1);
  193.             } 
  194.             else if (attr == RPLAY_PLAY) {
  195.                 *valp = RPLAY_DEFAULT_VOLUME;
  196.                 COPY(rp, valp, 1);
  197.             }
  198.         }
  199.         break; 
  200.          
  201.     default:
  202.         rplay_errno = RPLAY_ERROR_ATTRIBUTE;
  203.         return -1;
  204.     } 
  205.  
  206.     va_end(args);
  207.  
  208.     return 0;
  209. }
  210.  
  211. /*
  212.  * create a UDP socket for the given host
  213.  */
  214. int    rplay_open(host)
  215. char    *host;
  216. {
  217.     struct hostent        *hp;
  218. #ifdef INETD
  219.     struct servent        *sp;
  220. #endif INETD
  221.     int            rplay_fd;
  222.     u_long            addr;
  223.     struct sockaddr_in    s;
  224.     int            on = 1;
  225.  
  226.     rplay_errno = RPLAY_ERROR_NONE;
  227.  
  228. #ifdef INETD
  229.     sp = getservbyname("rplay", "udp");
  230.     if (sp == NULL) {
  231.         rplay_errno = RPLAY_ERROR_SERVICE;
  232.         return -1;
  233.     }
  234. #endif INETD
  235.  
  236.     bzero(&s, sizeof(s));
  237.  
  238.     addr = inet_addr(host);
  239.     if (addr == 0xffffffff) {
  240.         hp = gethostbyname(host);
  241.         if (hp == NULL) {
  242.             rplay_errno = RPLAY_ERROR_HOST;
  243.             return -1;
  244.         }
  245.         bcopy(hp->h_addr, &s.sin_addr.s_addr, hp->h_length);
  246.     }
  247.     else {
  248.         bcopy(&addr, &s.sin_addr.s_addr, sizeof(addr));
  249.     }
  250.  
  251. #ifdef INETD
  252.     s.sin_port = sp->s_port;
  253. #else
  254.     s.sin_port = htons(RPLAY_PORT);
  255. #endif INETD
  256.     s.sin_family = AF_INET;
  257.  
  258.     rplay_fd = socket(AF_INET, SOCK_DGRAM, 0);
  259.     if (rplay_fd < 0) {
  260.         rplay_errno = RPLAY_ERROR_SOCKET;
  261.         return -1;
  262.     }
  263.  
  264.     if (connect(rplay_fd, &s, sizeof(s)) < 0) {
  265.         rplay_errno = RPLAY_ERROR_CONNECT;
  266.         return -1;
  267.     }
  268.  
  269.     /*
  270.      * enable broadcasting
  271.      */
  272.     if (setsockopt(rplay_fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
  273.         rplay_errno = RPLAY_ERROR_BROADCAST;
  274.         return -1;
  275.     }
  276.  
  277.     return rplay_fd;
  278. }
  279.  
  280. /*
  281.  * write the RPLAY packet to the given socket descriptor
  282.  */
  283. int    rplay(rplay_fd, rp)
  284. int    rplay_fd;
  285. RPLAY    *rp;
  286. {
  287.     rplay_errno = RPLAY_ERROR_NONE;
  288.  
  289.     if (write(rplay_fd, rp->buf, rp->len) != rp->len) {
  290.         rplay_errno = RPLAY_ERROR_WRITE;
  291.         return -1;
  292.     }
  293.  
  294.     return 0;
  295. }
  296.  
  297. /*
  298.  * close the given rplay socket descriptor
  299.  */
  300. int    rplay_close(rplay_fd)
  301. int    rplay_fd;
  302. {
  303.     rplay_errno = RPLAY_ERROR_NONE;
  304.  
  305.     if (close(rplay_fd) < 0) {
  306.         rplay_errno = RPLAY_ERROR_CLOSE;
  307.         return -1;
  308.     }
  309.  
  310.     return 0;
  311. }
  312.  
  313. /*
  314.  * report an rplay error to stderr
  315.  */
  316. rplay_perror(s)
  317. char    *s;
  318. {
  319.     fprintf(stderr, "%s: %s\n", s, rplay_errlist[rplay_errno]);
  320. }
  321.